#ifndef __NET__H__
#define __NET__H__
#include "PluginModule/Platform.h"
#include "PluginModule/INet.h"

#include <thread>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/thread.h>
#include <event2/event_compat.h>

#pragma pack(push,1)
namespace FragrantGrass
{
	typedef std::map<SOCK, NetHandle*> NetHandleMap;
	typedef std::vector<SOCK> NetHandleArray;

	class Net : public INet
	{
	public:
		template<typename BaseType>
		Net(BaseType* pBaseType, void (BaseType::* msg_handler)(SOCK,int, const char*,uint32_t), void (BaseType::* event_handler)(SOCK,FG_NET_EVENT,INet*), bool tcpStream = false)
		{
			m_run_as_server = false;
			m_tcpStream = tcpStream;
			m_get_ready = false;
			m_port = 0;
			m_ip.clear();
			m_event_base = NULL;
			m_cb_read = std::bind(msg_handler, pBaseType, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
			m_cb_event = std::bind(event_handler, pBaseType, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
			m_msg_recieved_cnt = 0;
			m_max_client_cnt = 0;
			m_cpu_count = 0;
			m_listener = NULL;
			m_buffer_size = 0;
		}

	public:
		Net();
		virtual ~Net();

		virtual int init_as_client(const char* ip, unsigned short port);
		virtual int init_as_server(unsigned int max_client_cnt, unsigned short port, int cpu_count);
		virtual int expand_buffer_size(unsigned int size);
		virtual bool execute();
		virtual bool destroy();
		virtual bool run_as_server();

		static void listener_cb(struct evconnlistener* listener, evutil_socket_t fd, struct sockaddr* sa, int socklen, void* user_data);
		static void conn_readcb(struct bufferevent* bev, void* user_data);
		static void conn_writecb(struct bufferevent* bev, void* user_data);
		static void conn_eventcb(struct bufferevent* bev, short events, void* user_data);
		static void log_cb(int severity, const char* msg);
		static void event_fatal_cb(int err);

		bool add_net_handle(SOCK fd, NetHandle* handle);
		bool close_net_handle(SOCK fd);

		virtual bool send_msg(const char* msg, uint32_t len, SOCK fd);
		virtual bool send_msg_with_out_head(int16_t id, const char* msg, uint32_t len,SOCK fd);
		virtual bool send_msg_to_all_client(const char* msg, uint32_t len);
		virtual bool send_msg_to_all_client_with_out_head(int16_t id,const char* msg, uint32_t len);
		virtual bool send_msg_to_specific_clients(const char* msg, uint32_t len, const std::list<SOCK>& clients);
		virtual bool send_msg_to_specific_clients_with_out_head(int16_t id,const char* msg, uint32_t len, const std::list<SOCK>& clients);

	private:
		bool dismantle(NetHandle* pHandle);

		int decode(const char* data, uint32_t len, MsgHead& head);
		int encode(uint16_t id, const char* data, uint32_t len, std::string& out_data);

		int init_client_net(const std::string& ip,int port);
		int init_server_net();

		bool close_all_sockets();
		void execute_close();
		void close_net_handle_immediately(SOCK fd);

	private:
		bool m_tcpStream;
		bool m_run_as_server;
		bool m_get_ready;
		unsigned short m_port;
		std::string m_ip;
		struct event_base* m_event_base;
		NET_MESSAGE_HANDLER_FUNCTOR m_cb_read;
		NET_EVENT_HANDLER_FUNCTOR m_cb_event;
		int m_msg_recieved_cnt;
		NetHandleMap m_net_handle_impls;
		NetHandleArray m_removed_net_handles;
		int m_max_client_cnt;
		int m_cpu_count;
		int m_buffer_size;
		struct evconnlistener* m_listener;
	};
}
#pragma pack(pop)
#endif//__NET__H__